package org.btik.lightweb.interceptor;

import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.btik.light.server.platform.common.api.bean.user.UserVo;
import org.btik.light.tool.type.StringUtil;
import org.btik.lightweb.client.login.LoginController;
import org.btik.lightweb.util.WebUtil;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.function.Function;

/**
 * @author lustre
 * @since 2023/6/19 0:06
 */
public class UserLoginInterceptor {

    private static final byte[] UNAUTHORIZED = "<h1>401</h1>".getBytes(StandardCharsets.UTF_8);

    private static final byte[] FORBIDDEN = "<h1>403</h1>".getBytes(StandardCharsets.UTF_8);

    /**
     *检查用户登录并回调用户
     * @param userChecker 当用户会话存在且有效的时候，回调此函数进一步检查
     */
    public static boolean checkUserLoginAnd(HttpServletRequest request, HttpServletResponse response, Function<UserVo, Boolean> userChecker) throws IOException {
        HttpSession session = request.getSession(false);
        UserVo loginUser;
        if (session == null || (loginUser = (UserVo) session.getAttribute(LoginController.CURRENT_USER)) == null) {
            onNoLogin(response);
            return false;
        }
        // session的另一个身份，用于防止sessionId的窃取
        String sessionKey = (String) session.getAttribute(LoginController.SESSION_KEY);
        if (StringUtil.isEmpty(sessionKey)) {
            forbidden(response);
            return false;
        }
        String requestFrom = WebUtil.getRequestFrom(request);
        if (!requestFrom.equals(sessionKey)) {
            forbidden(response);
            return false;
        }
        if (!loginUser.isEnable()) {
            forbidden(response);
            return false;
        }

        return userChecker.apply(loginUser);
    }

    private static void onNoLogin(HttpServletResponse response) throws IOException {
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.setContentType("text/html; charset=UTF-8");
        ServletOutputStream outputStream = response.getOutputStream();
        outputStream.write(UNAUTHORIZED);
        outputStream.flush();

    }

    private static void forbidden(HttpServletResponse response) throws IOException {

        response.setStatus(HttpServletResponse.SC_FORBIDDEN);
        response.setContentType("text/html; charset=UTF-8");
        ServletOutputStream outputStream = response.getOutputStream();
        outputStream.write(FORBIDDEN);
        outputStream.flush();
    }
}
